﻿using System;
using System.Threading.Tasks;

namespace ConsoleDemo
{
    /// <summary>
    /// 异步编程 Task、async、await
    /// </summary>
    public class TaskDemo
    {
        public static void DelayDemo()
        {
            Console.WriteLine("1:" + DateTime.Now.ToString());
            var t = Task.Run(async delegate
            {
                await Console.Out.WriteLineAsync("2:" + DateTime.Now.ToString());
                await Task.Delay(TimeSpan.FromSeconds(4));
                await Console.Out.WriteLineAsync("3:" + DateTime.Now.ToString());
                return 42;
            });
            Console.WriteLine("4:" + DateTime.Now.ToString());
            t.Wait();
            Console.WriteLine("5:" + DateTime.Now.ToString());
            Console.WriteLine("Task t Status: {0}, Result: {1}",
                              t.Status, t.Result);
        }

        public static void YieldDemo()
        {
            Task<int> value = FindSeriesSum(1_000_000);
            CountBig(1_000_000); CountBig(1_000_000);
            CountBig(1_000_000); CountBig(1_000_000);
            Console.WriteLine($"Sum: {value.Result}");
        }

        public static async Task<int> FindSeriesSum(int i1)
        {
            int sum = 0;
            for (int j = 0; j < i1; j++)
            {
                sum += j;
                if (i1 / 1000 == 0)
                {
                    await Task.Yield();
                }
            }
            return sum;
        }

        private static void CountBig(int p)
        {
            for (int i = 0; i < p; i++)
                ;
        }

        /// <summary>
        /// Parallel 类 提供对并行循环和区域的支持。
        /// 执行 for 循环，其中可能会并行运行迭代。
        /// </summary>
        public static void ParallelDemo()
        {
            ParallelLoopResult result = Parallel.For(0, 100, ctr =>
            {
                Random rnd = new Random(ctr * 100000);
                Byte[] bytes = new Byte[100];
                rnd.NextBytes(bytes);
                int sum = 0;
                foreach (var byt in bytes)
                    sum += byt;
                Console.WriteLine("Iteration {0,2}: {1:N0}", ctr, sum);
            });
            Console.WriteLine("Result: {0}", result.IsCompleted ? "Completed Normally" :
                                                                   String.Format("Completed to {0}", result.LowestBreakIteration));
        }

        public static void ParallelDemo2()
        {
            int N = 1000;
            // Using a named method.
            Parallel.For(0, N, Method2);

            // Using an anonymous method.
            Parallel.For(0, N, delegate (int i)
            {
                Console.WriteLine("{0,2}, Method3", i);
            });

            // Using a lambda expression.
            Parallel.For(0, N, i =>
            {
                Console.WriteLine("{0,2}, Method4", i);
            });
        }


        static void Method2(int i)
        {
            Console.WriteLine("{0,2}, Method2", i);
        }
    }
}
